package com.graden.background.service.sysuser.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.graden.background.common.conf.aop.sso.AopResourceUserInfoBean;
import com.graden.background.common.utils.exception.ExceptionManager;
import com.graden.background.common.utils.md5.MD5Utils;
import com.graden.background.common.utils.validate.ValidateUtils;
import com.graden.background.controller.sysuser.vo.*;
import com.graden.background.repository.sysmenu.entity.SysMenu;
import com.graden.background.repository.sysmenufunction.entity.SysMenuFunction;
import com.graden.background.repository.sysrole.SysRoleMapper;
import com.graden.background.repository.sysrole.entity.SysRole;
import com.graden.background.repository.sysrolefunction.entity.SysRoleFunction;
import com.graden.background.repository.sysrolemenu.entity.SysRoleMenu;
import com.graden.background.repository.sysroleuser.entity.SysRoleUser;
import com.graden.background.repository.systoken.entity.SysToken;
import com.graden.background.repository.sysuser.SysUserMapper;
import com.graden.background.repository.sysuser.entity.SysUser;
import com.graden.background.service.sysmenu.ISysMenuService;
import com.graden.background.service.sysmenufunction.ISysMenuFunctionService;
import com.graden.background.service.sysrolefunction.ISysRoleFunctionService;
import com.graden.background.service.sysrolemenu.ISysRoleMenuService;
import com.graden.background.service.sysroleuser.ISysRoleUserService;
import com.graden.background.service.systoken.ISysTokenService;
import com.graden.background.service.sysuser.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 系统用户服务实现类
 * </p>
 *
 * @author zjf
 * @since 2019-03-21
 */
@Slf4j
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {


	@Resource
	ApplicationContext applicationContext;

	@Resource
	ExceptionManager exceptionManager;

	@Resource
	SysUserMapper sysUserMapper;

	@Resource
	SysRoleMapper sysRoleMapper;

	@Resource
	ISysRoleUserService iSysRoleUserService;

	@Resource
	ISysTokenService iSysTokenService;

	@Resource
	ISysRoleFunctionService iSysRoleFunctionService;

	@Resource
	ISysRoleMenuService iSysRoleMenuService;

	@Resource
	ISysMenuFunctionService iSysMenuFunctionService;

	@Resource
	ISysMenuService iSysMenuService;



	/**
	 * 账号密码登录的时候：检查登录
	 */
	@Transactional
	@Override
	public JSONObject checkLogin(UserLoginVO userLoginVO) {

		SysUser sysUserEntity = new SysUser();
		sysUserEntity.setBipCode(userLoginVO.getUser());

		try {
			sysUserEntity.setPassword(MD5Utils.md5Bit16Lower(userLoginVO.getPwd()));
		} catch (Exception e) {
			log.error("账号：{}，加密失败", userLoginVO.getUser());
			throw exceptionManager.create("LOGIN_0005");
		}

		QueryWrapper<SysUser> querySysUserWrapper = new QueryWrapper<>();
		querySysUserWrapper.eq("bip_code", sysUserEntity.getBipCode());
		querySysUserWrapper.eq("password", sysUserEntity.getPassword());

		SysUser resultUser = this.getOne(querySysUserWrapper);

		if (Objects.isNull(resultUser)) {
			throw exceptionManager.create("LOGIN_0004");
		}

		if (!resultUser.getStatus()) {
			throw exceptionManager.create("LOGIN_0007");
		}


		// 根据bipCode生成token;
		String token;
		try {
			token = MD5Utils.md5Bit16Lower(userLoginVO.getUser()+LocalDateTime.now().toString());
		} catch (Exception e) {
			log.error("账号：{}，生成token失败;", userLoginVO.getUser());
			throw exceptionManager.create("LOGIN_0006");
		}

		if (token != null) {
			//更新或插入token
			iSysTokenService.save(token, sysUserEntity.getBipCode());

			//注入指定BIP账号的用户信息
			this.injectUserRequestScope(resultUser);

		}

		JSONObject jsonObject = new JSONObject();
		jsonObject.put("token", token);
		return jsonObject;
	}

	@Override
	public String logout(String token) {

		SysToken sysToken = new SysToken();
		sysToken.setToken(null);
		sysToken.setRefreshTime(null);
		sysToken.setUpdateTime(LocalDateTime.now());

		QueryWrapper<SysToken> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("token", token);
		iSysTokenService.update(sysToken, queryWrapper);

		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
		requestAttributes.getRequest().getSession().invalidate();  // 清楚session


		return "注销成功";
	}

	/**
	 * 注入用户单例
	 */
	@Override
	public void injectUserRequestScope(SysUser sysUser) {

		//注入用户信息单例
		AopResourceUserInfoBean aopResourceUserInfoBean = applicationContext.getBean(AopResourceUserInfoBean.class);
		BeanUtils.copyProperties(sysUser, aopResourceUserInfoBean);
		aopResourceUserInfoBean.setId(sysUser.getId());

		// 判断是否系统管理员
		if (sysUser.getIsAdmin()) {

			// 全菜单权限
			List<SysMenu> sysMenuList = iSysMenuService.list();
			Integer[] menus = new Integer[sysMenuList.size()];
			for (int i = 0; i < sysMenuList.size(); i++) {
				menus[i] = sysMenuList.get(i).getId();
			}
			aopResourceUserInfoBean.setMenus(menus);

			// 全功能权限
			List<SysMenuFunction> sysMenuFunctionList = iSysMenuFunctionService.list();
			Integer[] functions = new Integer[sysMenuFunctionList.size()];
			for (int i = 0; i < sysMenuFunctionList.size(); i++) {
				functions[i] = sysMenuFunctionList.get(i).getId();
			}
			aopResourceUserInfoBean.setFunctions(functions);

			// 全菜单列表
			aopResourceUserInfoBean.setMenusJson(JSON.parseArray(JSON.toJSONString(iSysRoleMenuService.getRoleMenuTree(sysUser.getIsAdmin()))));

			return;
		}

		//根据user_id获取角色
		QueryWrapper<SysRoleUser> queryRoleUserWrapper = new QueryWrapper<>();
		queryRoleUserWrapper.eq("user_id", sysUser.getId());
		SysRoleUser sysRoleUser = iSysRoleUserService.getOne(queryRoleUserWrapper);

		if (Objects.nonNull(sysRoleUser)) {

			//根据role_id获取角色信息
			QueryWrapper<SysRole> queryRoleWrapper = new QueryWrapper<>();
			queryRoleWrapper.eq("id", sysRoleUser.getRoleId());
			List<SysRole> sysRoleList = sysRoleMapper.selectList(queryRoleWrapper);
			aopResourceUserInfoBean.setSysRoleList(sysRoleList);

			//根据role_id获取菜单权限
			QueryWrapper<SysRoleMenu> queryRoleMenuWrapper = new QueryWrapper<>();
			queryRoleMenuWrapper.eq("role_id", sysRoleUser.getRoleId());
			List<SysRoleMenu> sysRoleMenus = iSysRoleMenuService.list(queryRoleMenuWrapper);
			Integer[] menus = new Integer[sysRoleMenus.size()];
			for (int i = 0; i < sysRoleMenus.size(); i++) {
				menus[i] = sysRoleMenus.get(i).getMenuId();
			}
			aopResourceUserInfoBean.setMenus(menus);

			//根据role_id获取功能权限
			QueryWrapper<SysRoleFunction> queryRoleFunctionWrapper = new QueryWrapper<>();
			queryRoleFunctionWrapper.eq("role_id", sysRoleUser.getRoleId());
			List<SysRoleFunction> sysRoleFunctions = iSysRoleFunctionService.list(queryRoleFunctionWrapper);
			Integer[] functions = new Integer[sysRoleFunctions.size()];
			for (int i = 0; i < sysRoleFunctions.size(); i++) {
				functions[i] = sysRoleFunctions.get(i).getFunctionId();
			}
			aopResourceUserInfoBean.setFunctions(functions);

			//获取根据role_id获取菜单权限（树状）
			aopResourceUserInfoBean.setMenusJson(JSON.parseArray(JSON.toJSONString(iSysRoleMenuService.getRoleMenuTree(sysUser.getIsAdmin()))));
		}
	}

	/**
	 * 是否存在权限
	 */
	@Override
	public boolean existPower(int functionId) {
		AopResourceUserInfoBean aopResourceUserInfoBean = applicationContext.getBean(AopResourceUserInfoBean.class);

		if (Objects.isNull(aopResourceUserInfoBean.getSysRoleList()) || aopResourceUserInfoBean.getSysRoleList().isEmpty()) {
			throw exceptionManager.create("USER_0008");
		}
		if (Objects.isNull(aopResourceUserInfoBean.getFunctions())) {
			throw exceptionManager.create("USER_0009");
		}

		for (Integer item : aopResourceUserInfoBean.getFunctions()) {
			if (functionId == item) {
				return true;
			}
		}

		return false;
	}

	/**
	 * 分页查询
	 */
	@Override
	public PageInfo getAllByPage(int pageNo, int pageSize, UserSelectVO userSelectVO) {

		PageHelper.startPage(pageNo, pageSize);

		SysUser sysUser = new SysUser();
		BeanUtils.copyProperties(userSelectVO,sysUser);

		return new PageInfo<>(sysUserMapper.select(sysUser));
	}

	/**
	 * 添加系统用户
	 */
	@Transactional
	@Override
	public void addUser(UserAddVO userAddVO) {

		if (!ValidateUtils.isENG_NUM(userAddVO.getBipCode())) {
			throw exceptionManager.create("USER_0018");
		}


		//判断有没有重复的bipCode
		QueryWrapper<SysUser> sysUserWrapper = new QueryWrapper<>();
		sysUserWrapper.eq("bip_code", userAddVO.getBipCode());

		SysUser resultUser = sysUserMapper.selectOne(sysUserWrapper);
		if (Objects.nonNull(resultUser)) {
			throw exceptionManager.create("USER_0005");
		}

		SysUser sysUserEntity = new SysUser();
		BeanUtils.copyProperties(userAddVO, sysUserEntity);
		sysUserEntity.setId(0);
		sysUserEntity.setName(userAddVO.getBipCode());
		sysUserEntity.setIsAdmin(false);
		sysUserEntity.setStatus(true);
		sysUserEntity.setCreateTime(LocalDateTime.now());
		sysUserEntity.setUpdateTime(LocalDateTime.now());

		try {
			sysUserEntity.setPassword(MD5Utils.md5Bit16Lower("123456"));
		} catch (Exception e) {
			log.error("账号：{}，加密失败", userAddVO.getBipCode());
			throw exceptionManager.create("LOGIN_0005");
		}

		sysUserMapper.insertUser(sysUserEntity);

		//添加所绑定的角色
		Integer[] roleIds = userAddVO.getRoleIds();

		if (!Objects.isNull(roleIds)) {
			for (Integer roleId : roleIds) {
				if (!Objects.isNull(roleId)) {
					SysRoleUser sysRoleUser = new SysRoleUser();
					sysRoleUser.setId(0);
					sysRoleUser.setUserId(sysUserEntity.getId());
					sysRoleUser.setRoleId(roleId);
					sysRoleUser.setCreateTime(LocalDateTime.now());
					sysRoleUser.setUpdateTime(LocalDateTime.now());
					iSysRoleUserService.save(sysRoleUser);
				}
			}
		}

	}

	/**
	 * 更改用户信息
	 */
	@Transactional
	@Override
	public void updateUser(UserRoleUpdateVO userUpdateVO) {

		SysUser resultSysUser = sysUserMapper.selectById(userUpdateVO.getId());

		if (Objects.isNull(resultSysUser)) {
			throw exceptionManager.create("USER_0007");
		}

		SysUser sysUserEntity = new SysUser();
		BeanUtils.copyProperties(userUpdateVO, sysUserEntity);
		sysUserEntity.setUpdateTime(LocalDateTime.now());

		try {
			if (StringUtils.isNotEmpty(sysUserEntity.getPassword())) {
				sysUserEntity.setPassword(MD5Utils.md5Bit16Lower(sysUserEntity.getPassword()));
			}
		} catch (UnsupportedEncodingException e) {
			log.error("账号：{}，加密失败", resultSysUser.getBipCode());
			throw exceptionManager.create("LOGIN_0005");
		} catch (NoSuchAlgorithmException e) {
			log.error("账号：{}，加密失败", resultSysUser.getBipCode());
			throw exceptionManager.create("LOGIN_0005");
		}
		//更新user表信息
		sysUserMapper.updateById(sysUserEntity);

		//删除绑定的角色
		iSysRoleUserService.deleteRoleUserByUserId(sysUserEntity.getId());

		//重新添加绑定的角色
		Integer[] roleIds = userUpdateVO.getRoleIds();
		iSysRoleUserService.saveRoleUser(sysUserEntity.getId(), roleIds);

	}

	/**
	 * 修改密码
	 */
	@Override
	public void updatePassword(UserPwdUpdateVO userPwdUpdateVO) {

		//对比两个密码
		if (!userPwdUpdateVO.getNewPassword().equals(userPwdUpdateVO.getRepeatPassword())) {
			throw exceptionManager.create("USER_0014");
		}

		AopResourceUserInfoBean userInfo = applicationContext.getBean(AopResourceUserInfoBean.class);

		SysUser sysUser = this.getSysUserByBipCode(userInfo.getBipCode());

		if (sysUser == null) {
			throw exceptionManager.create("AUTH_0004");
		}

		try {
			//验证旧密码
			if (!sysUser.getPassword().equals(MD5Utils.md5Bit16Lower(userPwdUpdateVO.getOldPassword()))) {
				throw exceptionManager.create("USER_0015");
			}

			UpdateWrapper updateWrapper = new UpdateWrapper();
			updateWrapper.eq("bip_code", userInfo.getBipCode());
			updateWrapper.set("password", MD5Utils.md5Bit16Lower(userPwdUpdateVO.getNewPassword()));
			this.update(updateWrapper);
		} catch (UnsupportedEncodingException e) {
			log.error("账号：{}，加密失败", userInfo.getBipCode());
			throw exceptionManager.create("LOGIN_0005");
		} catch (NoSuchAlgorithmException e) {
			log.error("账号：{}，加密失败", userInfo.getBipCode());
			throw exceptionManager.create("LOGIN_0005");
		}

	}

	/**
	 * 激活用户信息
	 */
	@Override
	public void activateUser(UserActivateVO userActivateVO) {

		//判断当前登录人是否为管理员
		SysUser resultSysUser = sysUserMapper.selectById(userActivateVO.getId());

		if (Objects.isNull(resultSysUser)) {
			throw exceptionManager.create("USER_0007");
		}

		SysUser sysUserEntity = new SysUser();
		BeanUtils.copyProperties(userActivateVO, sysUserEntity);
		sysUserEntity.setUpdateTime(LocalDateTime.now());

		sysUserMapper.updateById(sysUserEntity);
	}

	/**
	 * 物理删除用户信息
	 */
	@Transactional
	@Override
	public void delete(int id) {

		sysUserMapper.delete(id);

		//删除与角色用户关联表的数据
		QueryWrapper<SysRoleUser> querySysRoleUserWrapper = new QueryWrapper<>();
		querySysRoleUserWrapper.eq("user_id", id);
		iSysRoleUserService.remove(querySysRoleUserWrapper);
	}

	/**
	 * 根据BipCode查询用户信息
	 */
	@Override
	public SysUser getSysUserByBipCode(String bipCode) {

		SysUser sysUserEntity = new SysUser();
		sysUserEntity.setBipCode(bipCode);

		QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("bip_code", bipCode);
		queryWrapper.eq("status", true);
		return this.getOne(queryWrapper);
	}
}
